/*
 * Copyright 2011-2025 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0.
 * See `LICENSE` in the project root for license information.
 */

package me.ijleex.jmh.benchmark.largefile;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

/**
 * LargeFileBenchmark.
 *
 * @author liym
 * @since 2020-07-04 13:47 新建
 */
@Warmup(iterations = 5) // 预热的次数
@Measurement(iterations = 5)
@Fork(1) // 进程数
@BenchmarkMode(Mode.Throughput)
public class LargeFileBenchmark {

    private static final String PATH = "D:/TDDOWNLOAD/勇敢者游戏2：再战巅峰.特效中英字幕.Jumanji.The.Next.Level.2019.BD1080P.X264.AAC.English&Mandarin.CHS-ENG.Mp4Ba.mp4";

    /**
     * 文件分块大小（100MB）
     */
    public static final int DEFAULT_CHUNK_SIZE = 100 * 1024 * 1024;

    public static final byte[] EMPTY_BYTE = new byte[0];

    /**
     * https://www.cnblogs.com/lyftest/p/6564282.html
     *
     * @return 文件块内容
     */
    @Benchmark
    public byte[] readByMappedByteBuffer() {
        Path file = Paths.get(PATH);

        try (FileChannel fileChannel = FileChannel.open(file, StandardOpenOption.READ)) {

            MappedByteBuffer chunkBuf = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, DEFAULT_CHUNK_SIZE);

            byte[] array = new byte[chunkBuf.limit()];
            chunkBuf.get(array);
            chunkBuf.flip();
            return array;
        } catch (IOException e) {
            return EMPTY_BYTE;
        }
    }

    /**
     * @return 文件块内容
     */
    @Benchmark
    public byte[] readByAsynchronousFileChannel() {
        Path file = Paths.get(PATH);

        try (AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(file, StandardOpenOption.READ)) {

            ByteBuffer chunkBuf = ByteBuffer.allocate(DEFAULT_CHUNK_SIZE);
            Future<Integer> future = fileChannel.read(chunkBuf, 0L);

            while (!future.isDone()) {
                TimeUnit.MILLISECONDS.sleep(1L);
            }

            chunkBuf.flip();
            return chunkBuf.array();
        } catch (IOException e) {
            return EMPTY_BYTE;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return EMPTY_BYTE;
        }
    }

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(LargeFileBenchmark.class.getName())
                .build();

        new Runner(options).run();
    }

}
